﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using MvcApplication9.Models;

public class Engine
{
    public static string GetMd5Hash(string input)
    {
        // Функция возвращает Md5 хешь входной строки

        MD5 md5Hasher = MD5.Create();

        // MD5 принимает байтовый массив на вход
        byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
        StringBuilder sBuilder = new StringBuilder();
        for (int i = 0; i < data.Length; i++)
        {
            // Посимвольно переводим в строку в hex
            sBuilder.Append(data[i].ToString("x2"));
        }
        return sBuilder.ToString();
    }

    public static string GenerateSalt()
    {
        // Функция генерирует случайную строку соли

        Random r = new Random();
        // Соль случайной длинны
        StringBuilder sBuilder = new StringBuilder();
        sBuilder.Length = r.Next(13, 31);

        for (int i = 0; i < sBuilder.Length; i++)
        {
            // генерируем соль ASCII символами
            sBuilder[i] = Convert.ToChar(r.Next(33, 126));
        }

        return sBuilder.ToString();
    }

    public static string Crypted(string pass, string salt = "f061cc51f0c69c9603e2f185f448db13")
    {
        // Three can keep a secret, if two of them are dead.
        // Функция солит пароль, xakep.ru/post/40336/ 

        string special = "~!@#$%^&*?";
        string crypted = GetMd5Hash(GetMd5Hash(salt) + GetMd5Hash(pass));
        string heshpass = GetMd5Hash(pass);

        StringBuilder result = new StringBuilder();
        result.Length = crypted.Length;

        for (int i = 0; i < crypted.Length; i++)
        {
            if (heshpass[i] >= '0' && heshpass[i] <= '9')
            {
                result[i] = special[heshpass[i] - '0'];
            }
            else if (heshpass[i] >= 'a' && heshpass[i] <= 'd')
            {
                result[i] = Char.ToUpper(crypted[i]);
            }
            else
            {
                result[i] = crypted[i];
            }
        }

        return GetMd5Hash(result.ToString());
    }

    public static bool Compare(string pass, string hash, string salt = "f061cc51f0c69c9603e2f185f448db13")
    {
        // Сравниваем пароль введенный пользователем, с солью и хешем хранимым в базе
        string crypted = Crypted(pass, salt);
        return (crypted == hash);
    }

    //Membership providers are too tough for me now
    public static bool ValidateUser(string username, string password)
    {
        User user = new User
        {
            Login = username
        };
        user = CRUD.Retrieve(user);
        if (user != null)
        {
            if (Engine.Compare(password, user.Password, user.Salt))
                return true;
        }
        return false;
    }

    //a bit ugly, but I don't want to goof with custom providers
    public static bool InRole(string username, string role)
    {
        User user = new User { Login = username };
        user = CRUD.Retrieve(user);
        if (user.Role == role) return true;
        return false;
    }
}
